using System;

using Microsoft.Practices.Composite.Logging;
using Microsoft.Practices.Composite.Presentation.Commands;
using Microsoft.Practices.Composite.Regions;

using Supremacy.Annotations;
using Supremacy.Client.Commands;
using Supremacy.Client.Events;
using Supremacy.Universe;

using System.Linq;

namespace Supremacy.Client.Services
{
    public interface INavigationService
    {
        bool ActivateScreen(string screenName);
        void NavigateToColony(Colony colony);
    }

    public class NavigationService : INavigationService
    {
        private readonly IDispatcherService _dispatcherService;
        private readonly IRegionManager _regionManager;
        private readonly INavigationCommandsProxy _navigationCommands;
        private readonly ILoggerFacade _logger;
        private readonly IClientContext _clientContext;

        public NavigationService(
            [NotNull] IDispatcherService dispatcherService,
            [NotNull] IRegionManager regionManager,
            [NotNull] INavigationCommandsProxy navigationCommands,
            [NotNull] ILoggerFacade logger,
            [NotNull] IClientContext clientContext)
        {
            if (dispatcherService == null)
                throw new ArgumentNullException("dispatcherService");
            if (regionManager == null)
                throw new ArgumentNullException("regionManager");
            if (navigationCommands == null)
                throw new ArgumentNullException("navigationCommands");
            if (logger == null)
                throw new ArgumentNullException("logger");
            if (clientContext == null)
                throw new ArgumentNullException("clientContext");

            _dispatcherService = dispatcherService;
            _regionManager = regionManager;
            _navigationCommands = navigationCommands;
            _logger = logger;
            _clientContext = clientContext;

            _navigationCommands.ActivateScreen.RegisterCommand(new DelegateCommand<string>(s => _dispatcherService.Invoke((Func<string, bool>)this.ActivateScreen, s)));
            _navigationCommands.NavigateToColony.RegisterCommand(new DelegateCommand<Colony>(NavigateToColony));
        }

        #region Implementation of INavigationService
        public bool ActivateScreen(string screenName)
        {
            var view = _regionManager.Regions[ClientRegions.GameScreens].GetView(screenName);
            if (view == null)
                return false;

            var activatingArgs = new ViewActivatingEventArgs(view);

            ClientEvents.ViewActivating.Publish(activatingArgs);

            if (activatingArgs.Cancel)
                return false;

            _logger.Log(
                string.Format("[INavigationService] Activating Screen: {0}", screenName),
                Category.Debug,
                Priority.None);

            _regionManager.Regions[ClientRegions.GameScreens].Activate(view);

            _logger.Log(
                string.Format("[INavigationService] Screen Activated: {0}", screenName),
                Category.Debug,
                Priority.None);

            return true;
        }

        public void NavigateToColony(Colony colony)
        {
            if (!_clientContext.IsGameInPlay)
                return;

            var playerEmpire = _clientContext.LocalPlayerEmpire;
            if (playerEmpire == null)
                return;

            if (colony == null)
                return;

            _logger.Log(
                string.Format("[INavigationService] Navigating to Colony: {0}", colony.Name),
                Category.Debug,
                Priority.None);

            var ownedByPlayer = (colony.OwnerID == playerEmpire.CivilizationID);

            if (!ownedByPlayer)
                ActivateScreen(StandardGameScreens.GalaxyScreen);

            GalaxyScreenCommands.SelectSector.Execute(colony.Sector);
            //GalaxyScreenCommands.CenterOnSector.Execute(colony.Sector);

            if (!ownedByPlayer)
                return;
        }
        #endregion
    }
}